package com.cwx.mychat.login.authentication;

import com.alibaba.fastjson.JSON;
import com.cwx.mychat.entity.constant.CodeConstant;
import com.cwx.mychat.entity.dto.LoginUserDto;
import com.cwx.mychat.entity.enums.ExceptionBizCodeEnum;
import com.cwx.mychat.exception.BusinessException;
import com.cwx.mychat.login.exception.CheckoutException;
import com.cwx.mychat.utils.bean.SpringBeanUtil;
import com.cwx.mychat.utils.redis.RedisUtil;
import com.cwx.mychat.utils.threadLocal.ThreadLocalUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 作者： cwx
 * 时间： 2024/10/18 23:30
 * 版本： 1.0
 * 注释： 实现登录的用户名密码验证
 */
@Slf4j
public class UsernameAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public UsernameAuthenticationFilter(AntPathRequestMatcher pathRequestMatcher, //登录url
                                           AuthenticationManager authenticationManager, //核心认证校验器
                                           AuthenticationSuccessHandler authenticationSuccessHandler, //登录成功逻辑
                                           AuthenticationFailureHandler authenticationFailureHandler) { //登录失败逻辑
        super(pathRequestMatcher);
        log.info("获取到url = {}", pathRequestMatcher.getPattern());
        setAuthenticationManager(authenticationManager);
        setAuthenticationSuccessHandler(authenticationSuccessHandler);
        setAuthenticationFailureHandler(authenticationFailureHandler);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        String checkCodeKey = null;
        RedisUtil redisUtil = SpringBeanUtil.getBean(RedisUtil.class);
        try{
            //提取数据
            String requestJsonData = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
            ObjectMapper objectMapper = new ObjectMapper();
            LoginUserDto loginUserDto = objectMapper.readValue(requestJsonData, LoginUserDto.class);
            String email = loginUserDto.getEmail();
            String password = loginUserDto.getPassword();
            checkCodeKey = loginUserDto.getCheckCodeKey();
            String checkCode = loginUserDto.getCheckCode();
            //校验验证码
            Object redisCheckCode = redisUtil.get(CodeConstant.REDIS_KEY_CHECK_CODE + checkCodeKey);
//            if (redisCheckCode == null || !redisCheckCode.toString().equalsIgnoreCase(checkCode)) {
//                throw new BusinessException(ExceptionBizCodeEnum.IMAGE_VALID_EXCEPTION);
//            }
            //将loginUserDto放入线程中
            ThreadLocalUtil.addLoginUserDto(loginUserDto);
            //封装成Spring Security需要的对象
            UsernameAuthentication usernameAuthentication = new UsernameAuthentication();
            usernameAuthentication.setEmail(email);
            usernameAuthentication.setPassword(password);
            usernameAuthentication.setAuthenticated(false);

            //开始登录认证
            log.info("开始登录验证：email为{}, 密码为{}, checkCodeKey为{}， checkCode为{}", email, password, checkCodeKey, checkCode);
            return getAuthenticationManager().authenticate(usernameAuthentication);
        }catch (Exception e){
            redisUtil.del(CodeConstant.REDIS_KEY_CHECK_CODE + checkCodeKey);
            log.error("提取数据产生异常", e);
            throw new CheckoutException(e.getMessage());
        }

    }
}
